package edu.pku.sei.transformation.editor.actions;

import org.eclipse.jface.action.Action;

import edu.pku.sei.modeler.exceptions.FactoryNotFoundException;
import edu.pku.sei.modeler.model.common.ModelRegistry;
import edu.pku.sei.modeler.model.core.MetaModel;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.core.MetaPackage;
import edu.pku.sei.modeler.model.structure.MetaDiagram;
import edu.pku.sei.modeler.model.structure.MetaNode;
import edu.pku.sei.modeler.model.structure.StructureFactory;
import edu.pku.sei.modeler.project.ProjectRegistry;
import edu.pku.sei.transformation.editor.binding.IDiagramBindingElement;
import edu.pku.sei.transformation.editor.internal.TransformationEditorPaletteFactory;
import edu.pku.sei.transformation.editor.model.AtomicTransformation;
import edu.pku.sei.transformation.editor.model.CompositeTransformation;
import edu.pku.sei.transformation.editor.model.Rule;
import edu.pku.sei.transformation.editor.model.Transformation;
import edu.pku.sei.transformation.editor.views.icons.IconsProvider;

public class OpenBindedDiagram extends Action {
	private IDiagramBindingElement element;
	private MetaModel model;

	public OpenBindedDiagram(IDiagramBindingElement element) {
		if (element instanceof Rule) {
			this.model = ((Rule) element).getModel();
			this.setImageDescriptor(IconsProvider
					.getImageDescriptor(IconsProvider.RULE_ICO));
		} else {
			this.model = ((Transformation) element).getModel();
			this.setImageDescriptor(IconsProvider
					.getImageDescriptor(IconsProvider.TRANSFORMATION_ICO));
		}
		this.element = element;
		this.setText("Open Diagram");

	}

	@Override
	public void run() {
		MetaDiagram diagram;
		diagram = getDiagram(element, model);
		openDiagram(diagram, model);
	}

	public MetaDiagram getDiagram(IDiagramBindingElement element,
			MetaModel model) {
		String diagramType;
		MetaPackage defaultPackage = (MetaPackage) model.getPackages().get(0);
		MetaDiagram diagram = element.getDiagram();

		if (diagram == null) {
			StructureFactory sFactory;
			try {
				sFactory = (StructureFactory) ModelRegistry.getRegistry()
						.getStructureFactory(model);
				diagram = sFactory.createMetaDiagram();

				if (element instanceof Rule) {
					diagram.setName(((Rule) element).getName());
					diagram
							.setType(TransformationEditorPaletteFactory.RULE_DIAGRAM);
					MetaNode relationNode = sFactory.createMetaNode();
					relationNode.setModelElement((MetaModelElement) element);
					relationNode.setReferenceShape(true);
					relationNode.setLocationX(100);
					relationNode.setLocationY(100);
					relationNode.setWidth(100);
					relationNode.setHeight(50);
					diagram.getNodes().add(relationNode);

				} else if (element instanceof AtomicTransformation) {
					diagram.setName(((AtomicTransformation) element).getName());
					diagram
							.setType(TransformationEditorPaletteFactory.RULE_STRUCTURE_DIAGRAM);
					AtomicTransformation trans = (AtomicTransformation) element;
					int x = 10, y = 10;
					/*
					 * for (Rule rule : trans.getAllRules()) { MetaNode node =
					 * sFactory.createMetaNode(); node.setModelElement(rule); if
					 * (rule.getOwner() != element)
					 * node.setReferenceShape(true); node.setLocationX(x);
					 * node.setLocationY(y); node.setWidth(100);
					 * node.setHeight(50); diagram.getNodes().add(node); if (y
					 * == 1000) { x += 130; y = 10; } else { y += 70; } }
					 */
				} else if (element instanceof CompositeTransformation) {
					diagram.setName(((CompositeTransformation) element)
							.getName());
					diagram
							.setType(TransformationEditorPaletteFactory.TRANSFORMATION_COMPOSITE_DIAGRAM);
					CompositeTransformation trans = (CompositeTransformation) element;
					int x = 10, y = 10;
					for (Object p : trans.getTypedModel()) {
						MetaNode node = sFactory.createMetaNode();
						node.setModelElement((MetaModelElement) p);
						node.setReferenceShape(true);
						node.setLocationX(x);
						node.setLocationY(y);
						node.setWidth(100);
						node.setHeight(50);
						diagram.getNodes().add(node);
						if (y == 1000) {
							x += 130;
							y = 10;
						} else {
							y += 70;
						}
					}
				}

			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (FactoryNotFoundException e) {
				e.printStackTrace();
			}
			element.setDiagram(diagram);
		}

		return diagram;
	}

	public void openDiagram(MetaDiagram diagram, MetaModel model) {
		ProjectRegistry.getDefault().openDiagram(diagram, model);
	}
}
